import styles from './tool.module.scss';
import {throttle, debounce} from 'lodash';
import React from 'react';
import {EE, prompt} from '@/utils';
import {addListener} from './helper/listener';
import {nanoid} from "nanoid";
import EnumOnFire from "@/pages/dv/constants/EnumOnFire";

interface IGridProps {
  stepX?: number;
  stepY?: number;
  color?: string;
}

class DrawTool {
  public container: any;
  public timer: any;
  public $screensContainer: any;
  public xLines: any;
  public yLines: any;
  public drawCharting: boolean;
  public isContinuousDraw: boolean;
  public startPosition: IPosition;

  constructor() {
    this.container = null;
    this.timer = null;
    this.drawCharting = false;// 正在画图表
    this.isContinuousDraw = false; // 是否连续作画
    this.$screensContainer = null;
    this.xLines = {};
    this.yLines = {};
    this.startPosition = {
      x: -200, // 200 = .dv_container.left
      y: -200, // 200 = .dv_container.top
    }

    this.removeDragLines = debounce(this.removeDragLines, 500);
  }

  initScreenContainer($container: Element) {
    if ($container) {
      this.$screensContainer = $container;
    } else {
      if (!this.$screensContainer) {
        const drawDom = document.querySelector('#screensContainer');
        if (drawDom) {
          this.$screensContainer = drawDom;
        } else {
          alert('操作失败! 无法定位画板');
        }
      }
    }
    return this.$screensContainer;
  }

  initCanvas($container: Element) {
    if ($container) {
      this.container = $container;
    } else {
      if (!this.container) {
        const drawDom = document.querySelector('#drawOuterBox');
        if (drawDom) {
          this.container = drawDom;
        } else {
          alert('操作失败! 无法初始化画板');
        }
      }
    }

    return this.container;
  }

  /**
   * 绘制组件
   * @param type
   * @param uid
   */
  drawNewChart(type: string, uid?: string){
    EE.fire(EnumOnFire.drawChart_emit, type, uid);
    EE.fire(EnumOnFire.drawChart_status, 'start');
  }

  /**
   * 绘画矩形
   * @param container
   * @param scale
   * @param onFinish
   */
  drawChartRect(container: any, scale: number, {
    onFinish
  }: { onFinish: Function }) {
    this.drawCharting = true; // 正在画图表
    this.isContinuousDraw = false; // 是否连续作画
    this.initCanvas(container);
    let painting: boolean = false;
    let x1: number = 0;
    let y1: number = 0;
    let w: number = 0;
    let h: number = 0;
    let box: any = null;
    let rectChartBox: any = null;
    let layer: number = 0;
    // 新增容器
    box = document.createElement('div');
    this.container.appendChild(box);


    const addReactLayer = (x: number, y: number, w: number, h: number) => {
      // console.log(x, y, w, h);
      if (layer > 0 && rectChartBox) {
        // 更新
        rectChartBox.style.left = x + 'px';
        rectChartBox.style.top = y + 'px';
        rectChartBox.style.width = w + 'px';
        rectChartBox.style.height = h + 'px';
      } else {
        // 新增
        rectChartBox = document.createElement('div');
        rectChartBox.classList.add('rectChartBox');
        rectChartBox.style.left = x + 'px';
        rectChartBox.style.top = y + 'px';
        rectChartBox.style.width = w + 'px';
        rectChartBox.style.height = h + 'px';
        box.appendChild(rectChartBox);
        // 增加actions

      }
      layer++;
    }

    const removeRectLayer = () => {
      this.container && this.container.removeChild(box);
    }

    const updateBox = (e: MouseEvent) => {
      e.stopPropagation();
      e.preventDefault();

      if (painting) {
        let x2 = e.offsetX;
        let y2 = e.offsetY;
        w = x2 - x1 > 0 ? x2 - x1 : 0;
        h = y2 - y1 > 0 ? y2 - y1 : 0;
        addReactLayer(x1, y1, w, h);
      }
    }

    box.onmousedown = (e: MouseEvent) => {
      e.stopPropagation()
      e.preventDefault()
      painting = true;
      x1 = e.offsetX;
      y1 = e.offsetY;
      w = 0;
      h = 0;
      EE.fire(EnumOnFire.drawChart_status, 'doing');

      const listener = addListener(box, 'mousemove', throttle(updateBox, 20));
      // box.addEventListener('mousemove', updateBox.bind(this), true);
      box.onmouseup = (e: MouseEvent) => {
        e.stopPropagation()
        e.preventDefault()
        addReactLayer(x1, y1, w, h);
        painting = false;
        if ((w < 10 && h < 10) || (w < 4 || h < 4)) {
          prompt.warn(`绘制尺寸过小[${w + ',' + h}]，请重新绘制！`);
        } else {
          // 检测是否按住了shift键连续绘画组件

          if (e.shiftKey) {
            this.isContinuousDraw = true;
            EE.fire(EnumOnFire.drawChart_status, 'pause')
            if (typeof onFinish === 'function') onFinish(x1, y1, w, h);
          } else {
            // 停止监听
            listener.destroy(() => {
              this.isContinuousDraw = false;
              this.drawCharting = false;
              EE.fire(EnumOnFire.drawChart_status, 'end')
              if (typeof onFinish === 'function') onFinish(x1, y1, w, h, true);
              removeRectLayer();
            });
          }
        }
      }
    }
  }

  drawXLine({left, top}: IPosition, scale: number, lineKey: string) {
    if (!lineKey || typeof lineKey !== 'string') lineKey = nanoid(6);
    if (this.xLines[lineKey]) {
      // 更新辅助线
      this.xLines[lineKey].style.top = (Math.abs(this.startPosition.y) + top * scale) + 'px';
      this.xLines[lineKey].style.width = (Math.abs(this.startPosition.x) + left * scale) + 'px';
      this.xLines[lineKey].firstChild.innerHTML = left + ', ' + top;
    } else {
      // 新增辅助线
      const $line = document.createElement('div');
      const text = document.createElement('span');
      text.innerHTML = left + ', ' + top;
      $line.appendChild(text);
      $line.classList.add(styles.xLine);
      this.$screensContainer.appendChild($line);
      this.xLines[lineKey] = $line
    }
  }

  drawYLine({left, top}: IPosition, scale: number, lineKey: string) {
    if (!lineKey || typeof lineKey !== 'string') lineKey = nanoid(6);
    const {x, y}: IPosition = this.startPosition;
    if (this.yLines[lineKey]) {
      // 更新辅助线
      this.yLines[lineKey].style.left = (Math.abs(x) + left * scale) + 'px';
      this.yLines[lineKey].style.height = (Math.abs(y) + top * scale) + 'px';
    } else {
      // 新增辅助线
      const $line = document.createElement('div');
      $line.classList.add(styles.yLine);
      this.$screensContainer.appendChild($line);
      this.yLines[lineKey] = $line
    }
  }


  /**
   * 添加、更新拖拽坐标辅助线
   * @param position
   * @param scale
   */
  drawDragLines(position: IPosition, scale: number) {
    this.drawXLine(position, scale, 'x');
    this.drawYLine(position, scale, 'y');
    this.removeDragLines();
  }

  /**
   * 删除拖拽坐标辅助线
   */
  removeDragLines() {
    if (this.xLines['x']) {
      // 更新辅助线
      this.xLines['x'].style.width = 0;
    }

    if (this.yLines['y']) {
      // 更新辅助线
      this.yLines['y'].style.height = 0;
    }
  }

  fillGrid(container: HTMLElement, {
    color = 'orange',
    stepX = 50,
    stepY = 50
  }: IGridProps) {

  }
}

export default new DrawTool();
